#pragma once

#include <stdint.h>
#include "li_basic.h"
#include "li_collections.h"

typedef enum
{
	RPEE_unexpected_error = -1,
	RPEE_variable_not_found = -2,
	RPEE_empty_input = -3,
	RPEE_invalid_expression = -4

} RPEErrors;

typedef struct
{
	union
	{
		uint32_t hashCode;
		void *fun;
	};
	int8_t xnary;			  // unary, binary, ternary
	int8_t priority : 7;	  // higher with bigger number
	int8_t associativity : 1; // left to right=0, right to left=1
} RPEOperator_t;

typedef RPEOperator_t *RPEOperator;
typedef Val_t RPEVal_t;
typedef RPEVal_t *RPEVal;

typedef enum
{
	RPETypeEmpty = 0,
	RPETypeImmediateNumber = 1,
	RPETypeVar = 2,
	RPETypeOperator = 4,
	RPETypeFunction = 8,
	RPETypeParentheses = 16,
	RPETypeBracket = 32,
} RPEType;
typedef struct
{
	union
	{
		RPEOperator_t operator;
		RPEVal_t val;
	};
	char type;
} RPEItem_t;
typedef RPEItem_t *RPEItem;

// for a compact type to substitute RPEItem_t
typedef struct
{
	void *fun;
	int8_t xnary;
} RPECompactOperator_t;
typedef RPECompactOperator_t *RPECompactOperator;
// typedef struct
// {
// 	str name;
// 	HASH hashCode;
// } RPECompactIdentity_t;
// typedef RPECompactIdentity_t *RPECompactIdentity;
typedef CVal RPECompactNumber_t;
typedef RPECompactNumber_t *RPECompactNumber;

typedef enum
{
	RPECEmpty = 0x00,
	RPECNumber = 0x10,
	RPECVar = 0x20,
	RPECFun = 0x30,
	RPECOperator = 0x40,
	RPECOperatorUnary = 0x80,
} RPECompactType;

void RPE_init();
const str _RPE_operator_to_str(void *f);
int fun_caller_adaptive(Fun fun, int numn, RPEVal *vals, RPEVal out_res);
Li_List RPE_compile(const char *exp, int len);
Li_List RPE_compile2(const char *exp, int len, Any push_arg_str, Li_List _arg_txt_segment);

Li_List RPE_compress(Li_List rpe);
int RPE_execute(Li_List rpe, void *vars, void *funs, void *call_arg, RPEVal out_res, void *stack_heap);
int RPE_execute_from_compact(int item_count, int8_t *types, void *vars, void *funs, void *call_arg, RPEVal out_res, void *stack_heap, const str text_segment);
int RPE_compile_get_len(const char *exp, int len);
